-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add caching for PriceReader #372
base: main
Are you sure you want to change the base?
Conversation
pkg/reader/price_reader.go
Outdated
tokenInfo map[ccipocr3.UnknownEncodedAddress]pluginconfig.TokenInfo | ||
ccipReader CCIPReader | ||
feedChain ccipocr3.ChainSelector | ||
decimalsCache cache.Cache[string, uint8] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i believe it can be just inMemCache
no need to tie it to decimals
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It depends if we have more than one cache. I'll leave it as-is for now and potentially update the name if this is the only cache of the class. wdyt?
internal/cache/cache.go
Outdated
) | ||
|
||
// Cache defines the interface for cache operations | ||
type Cache[K comparable, V any] interface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about an off the shelf library?
https://github.com/eko/gocache
https://github.com/allegro/bigcache
https://github.com/dgraph-io/ristretto
https://github.com/patrickmn/go-cache
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked the libs you provided and they look quite advanced. I'm not sure about our future requirements but our current needs are quite simple. It might makes sense to go homemade for our usecase.
Do you have any experience with those libs? What do you recommend?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I almost used ristretto for a project that needed high performance, but you're probably right that it's excessive for our needs.
Two trains of thought right now:
-
go-cache
seems like an excellent fit. It's extremely lightweight (a single file with ~1000 LOC), the interface is almost identical to the one you have, the project has the most stars. -
If we do roll our own, I bet we could come up with a clever optimization to time based expiration utilizing sequence numbers and multiple maps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can go with a with go-cache
and overload it with a custom logic to implement the customPolicy
. Something like this:
type CustomCache[K comparable, V any] struct {
cache *cache.Cache
customPolicy func(V) bool
mutex sync.RWMutex
}
func (c *CustomCache[K, V]) Get(key K) (V, bool) {
c.mutex.RLock()
defer c.mutex.RUnlock()
...
// Check custom policy
if c.customPolicy != nil && c.customPolicy(typedValue) {
c.cache.Delete(interface{}(key))
return zero, false
}
return typedValue, true
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see tests for the time based eviction with one test that is skipped with a TODO to make a proper background task to evict.
|
We are currently making many RPC calls to get token prices, which can slow down our system. This PR introduces a simple caching solution to store and reuse these values.
Changes made:
The implementation wraps go-cache and can be extended for other use cases. It supports: